/*
 * Group:PrePool K9-357 
 * 8/2010
 */
package dao;

import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;

import dto.DictionaryDTO;
import util.Controller;

/**
 *
 */
public class DictionariesDAO {
	public Logger LOG = Logger.getLogger("dao.DictionariesDAO");
	private List<DictionaryDTO> dictList = new ArrayList<DictionaryDTO>();

	public List<DictionaryDTO> getDictList() {
		return dictList;
	}

	public void setDictList(List<DictionaryDTO> dictList) {
		this.dictList = dictList;
	}

	/**
	 * load all dictionaries from database to the dictList
	 */
	public DictionariesDAO() {
		Connection cnn = null;
		PreparedStatement pstat = null;
		ResultSet rs = null;

		try {
			cnn = Controller.getConnection();
			pstat = cnn.prepareStatement("select * from m_dictionaries");
			rs = pstat.executeQuery();

			while (rs.next()) {
				DictionaryDTO dt = new DictionaryDTO();
				dt.setM_id(rs.getInt("m_id"));
				dt.setM_fromID(rs.getInt("m_fromID"));
				dt.setM_toID(rs.getInt("m_toID"));
				dt.setM_dicturl(rs.getString("m_dictURL"));
				dt.setM_delCount(rs.getInt("m_delCount"));
				dictList.add(dt);
			}
		} catch (Exception ex) {
		} finally {
			try {
				if (rs != null) {
					rs.close();
				}
				if (pstat != null) {
					pstat.close();
				}
				if (cnn != null) {
					cnn.close();
				}
			} catch (Exception ex) {
			}
		}
	}

	/**
	 * get an dictionary by its id
	 * 
	 * @param dictId
	 *            dictionary's Id
	 * @return
	 */
	public DictionaryDTO getDictionary(int dictId) {
		DictionaryDTO dict = null;

		for (int i = dictList.size(); i > 0;) {
			--i;
			dict = dictList.get(i);
			if (dict.getM_id() == dictId) {
				return dict;
			}
		}
		return null;
	}

	/**
	 * get an dictionary by its fromID and toID of languages
	 * 
	 * @param fromId
	 *            Id of base dictionary
	 * @param toId
	 *            Id of destination dictionary
	 * @return
	 */
	public List<DictionaryDTO> getDictionary(int fromId, int toId) {
		List<DictionaryDTO> listDict = new ArrayList<DictionaryDTO>();
		DictionaryDTO dict = null;

		for (int i = 0; i < dictList.size(); ++i) {
			dict = dictList.get(i);
			if (dict.getM_fromID() == fromId && dict.getM_toID() == toId) {
				listDict.add(dict);
			}
		}
		return listDict;
	}

	/**
	 * add a new dictionary
	 * 
	 * @param fromId
	 * @param toId
	 * @param dictURL
	 *            dictionary's URL
	 * @return
	 */
	public boolean addNewDictionary(int fromId, int toId, String dictURL) {

		// Warning: Could not to add new dictionary English-English
		DictionaryDTO dt;

		for (int i = dictList.size(); i > 0;) {
			--i;
			dt = dictList.get(i);
			if (dt.getM_fromID() == fromId && dt.getM_toID() == toId) {
				return false;
			}
		}

		boolean bOK = false;
		Connection cnn = null;
		CallableStatement cstat = null;
		ResultSet rs = null;

		// get dictionaries from data base and add to the list of dictionaries
		try {
			cnn = Controller.getConnection();
			cstat = cnn
					.prepareCall("{call m_dictionaries_insert(m_fromID, m_toID, m_dictUrl) values(?, ?, ?)}");
			cstat.setInt(1, fromId);
			cstat.setInt(2, toId);
			cstat.setString(3, dictURL);

			if (cstat.executeUpdate() == 1) {
				cstat.close();
				cstat = cnn
						.prepareCall("select m_id,m_delCount from m_dictionaries where m_fromID="
								+ fromId + " and m_toID=" + toId);
				rs = cstat.executeQuery();
				if (rs.next()) {
					DictionaryDTO dict = new DictionaryDTO();
					dict.setM_id(rs.getInt("m_id"));
					dict.setM_fromID(fromId);
					dict.setM_toID(toId);
					dict.setM_delCount(rs.getInt("m_delCount"));
					dictList.add(dict);
					bOK = true;
				}
			}
		} catch (Exception ex) {
		} finally {
			try {
				if (rs != null) {
					rs.close();
				}
				if (cstat != null) {
					cstat.close();
				}
				if (cnn != null) {
					cnn.close();
				}
			} catch (Exception ex) {
			}
		}
		System.out.println("add ok!");

		return bOK;
	}

	/**
	 * delete a dictionary
	 * 
	 * @param dictId
	 * @return
	 */
	public boolean deleteDict(int dictId) {
		boolean bOK = false;
		Connection cnn = null;
		// delete from m_dictionaries table
		CallableStatement cstatDelDict = null;

		try {
			cnn = Controller.getConnection();
			cstatDelDict = cnn.prepareCall("{call m_dictionaries_delete(?)}");
			cstatDelDict.setInt(1, dictId);

			for (int i = dictList.size(); i > 0;) {
				--i;
				// check if dictionary exists in the list
				if (dictList.get(i).getM_id() == dictId) {
					try {
						cstatDelDict.executeUpdate();
						bOK &= true;
					} catch (Exception ex) {
						bOK = false;
					} finally {
						cstatDelDict.close();
					}
					// remove dictionary from the list
					dictList.remove(i);
					break;
				}
			}
		} catch (Exception ex) {
			bOK = false;
		} finally {
			try {
				if (cstatDelDict != null) {
					cstatDelDict.close();
				}
			} catch (Exception ex) {
			}
		}
		return bOK;
	}

	/**
	 * create a new dictionary
	 * 
	 * @param fromId
	 * @param toId
	 * @param bookname
	 * @param fileName
	 * @param folderName
	 * @return
	 */
	public boolean createNewDictionary(int fromId, int toId, String bookname,
			String fileName, String folderName) {
		boolean bOK = false;

		if (this.getDictionary(fromId, toId) != null) {
			return false;
		}
		(new java.io.File(Controller.getDictRootFolder() + "/" + folderName))
				.mkdir();
		String url = Controller.getDictRootFolder() + "/" + folderName + "/"
				+ fileName;
		String dictFile = url + ".dict";
		String idxFile = url + ".idx";
		String ifoFile = url + ".ifo";

		if ((new java.io.File(dictFile)).exists()
				|| (new java.io.File(idxFile)).exists()
				|| (new java.io.File(ifoFile)).exists()) {
			return false;
		}

		try {
			DataOutputStream dt = new DataOutputStream(new FileOutputStream(
					dictFile));
			// java.io.FileWriter fw = new java.io.FileWriter(dictFile);
			String strFirstWord = "@00-database-info\nThis is the " + bookname
					+ " dictionary database of the Free Vietnamese Dic";
			dt.write(strFirstWord.getBytes());
			dt.flush();
			dt.close();

			dt = new DataOutputStream(new FileOutputStream(idxFile));
			dt.write('\0');
			dt.write(convertAnInt32(0));
			dt.write(convertAnInt32(strFirstWord.length()));
			dt.flush();
			dt.close();
			java.io.FileWriter fw = new java.io.FileWriter(ifoFile);
			fw.write("StarDict's dict ifo file\n");
			fw.write("version=2.4.2\n");
			fw.write("wordcount=1\n");
			fw.write("idxfilesize=9\n");
			fw.write("bookname=" + bookname + "\n");
			fw.write("author=G3-K9\n");
			fw.write("website=http://raiportal.fsofthcmworks.com\n");
			fw.write("description=convert to StarDict by FPT Software\n");
			fw.write("date=2005.10.09\n");
			fw.write("sametypesequence=m\n");
			fw.flush();
			fw.close();

			// add to database and the list
			if (this.addNewDictionary(fromId, toId, url)) {
				bOK = true;
			} else {
				(new java.io.File(dictFile)).delete();
				(new java.io.File(idxFile)).delete();
				(new java.io.File(ifoFile)).delete();
			}
		} catch (Exception ex) {
			bOK = false;
		}

		return bOK;
	}

	/**
	 * @param val
	 * @return
	 */
	public byte[] convertAnInt32(int val) {
		byte[] str = new byte[4];
		str[0] = (byte) ((val & 0xFF000000) >> 24);
		str[1] = (byte) ((val & 0x00FF0000) >> 16);
		str[2] = (byte) ((val & 0x0000FF00) >> 8);
		str[3] = (byte) ((val & 0x000000FF));
		return str;
	}

	/**
	 * @param dictID
	 * @param delCount
	 */
	public void updateDelCount(int dictID, int delCount) {
		Connection cnn = null;
		CallableStatement cstat = null;

		try {
			cnn = Controller.getConnection();
			cstat = cnn.prepareCall("{call update_dictionaries_delcount(?,?)}");
			cstat.setInt(1, dictID);
			cstat.setInt(2, delCount);
			cstat.executeUpdate();
		} catch (Exception ex) {
		} finally {
			try {
				if (cstat != null) {
					cstat.close();
				}
				if (cnn != null) {
					cnn.close();
				}
			} catch (Exception ex) {
			}
		}
	}
}